home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Sapphire Collection / Software Vault (Sapphire Collection) (Digital Impact).ISO / cdr47 / trace122.zip / TRACE1.ASM < prev    next >
Assembly Source File  |  1997-02-13  |  43KB  |  1,336 lines

  1.         page    60,132
  2.         .lfcond
  3.         title   "TRACE - Interrupt Tracer"
  4.         subttl  Introduction
  5.         page
  6.         comment \
  7.  
  8. TRACE is an INT tracer. It traps INT's, traces the registers at the entry
  9. to the INT, executes the INT itself, and then traces the regs at exit from
  10. the INT. It also allows the user at the keyboard to see all of this traced
  11. information, either at the screen or on the printer.
  12.  
  13. The INT's that are to be traced are specified in the source code (see config
  14. section below). Once defined, they may be enabled or disabled from the
  15. keyboard.
  16.  
  17.       <<< REBOOT AS SOON AS POSSIBLE AFTER INVOKING TRACE!!! >>>
  18.  
  19. This is not foolproof or bugfree. We use it 'cause it's a terrific tool
  20. for deprotecting copy-protected software. You use it at your own risk.
  21. When you've gotten a printout of the trace activity that interests you,
  22. reboot your system. Don't say that we didn't warn you.
  23.  
  24. Enjoy.
  25.  
  26.  
  27.       Usage is: TRACE [size]  
  28.  
  29.           where: size is the size of the trace table in K
  30.                  between 10 and 63, default is 30
  31.  
  32.  
  33. Known problems:
  34.  
  35.       Programs that use:  INT 21h function E0
  36.                           INT 2Eh 
  37.  
  38.  
  39.  
  40.         \
  41.         page
  42. code    segment para public 'code'
  43.         assume  cs:code,ds:code
  44.         public  trace_begin,trace_curr,trace_end,trace_bytes
  45.         public  ict_index,hndlr_index,prt_base
  46.         public  our_cs,test_cs,periscope
  47.         public  rec_sizes,interp,old_int_5,prtsc
  48.  
  49.         extrn   selvideo:near,selprint:near,print:near,print_hex:near
  50.         extrn   print_word:near,print_wordb:near,crlf:near,print_line:near
  51.         extrn   table_print:near
  52.         extrn   print_edit:near,feed:near,key:near,zap_hits:near
  53.         extrn   prt_sc:near
  54.         
  55.         extrn   do_traces:near,do_enable:near,disp_active:near,do_fcb:near
  56.         extrn   init:near
  57.  
  58.         extrn   trace_table:byte
  59.  
  60.         org     0100h
  61. start:  jmp     init
  62.  
  63.         include b:trace1e.aic
  64.  
  65.  
  66. ; note that the number of ict's is set by number_icts in trace1e.aic 
  67. ;      and implicetly in code throughout this module.
  68.  
  69. ; note that you need an ICT for some INT 21h AH = 0F0h for the
  70. ;      detection of TRACE already being installed feature to work
  71. ;      ICT with low ah = 0dh  and high ah = ffh works fine.
  72.  
  73. ;      ict parms are:
  74. ;          flags,flags2,int,low ah, high ah, saved cs:ip, 
  75. ;          count of entries,ict number
  76.  
  77. ;      ict flags are:
  78. ;          f_active tracing on at start-up
  79. ;          f_ret    far ret with original flags, flags on stack
  80. ;          f_ret2   far ret with updated flags, no flags on stack
  81. ;          f_iret   iret with original flags, no flags on stack
  82.  
  83. ;      ict flags2 are:
  84. ;          f_call   This call will return. Example INT 21H, in general 
  85.  
  86. ict0  ICT  <F_ACTIVE+F_RET2+F_ENABLE,F_CALL,013H,0,0ffh,0,0,0>            
  87.                                                       ;ROM BIOS INT 13h (all)
  88. ict1  ICT  <F_ACTIVE+F_RET+F_ENABLE,0,020h,0,0ffh,0,0,1>        
  89.                                                       ;DOS EXIT
  90. ict2  ICT  <F_ACTIVE+F_RET2,F_CALL,021H,0,0ch,0,0,2>                      
  91.                                                       ;DOS funcs 00h thru 0Ch
  92. ict3  ICT  <F_ACTIVE+F_RET2+F_ENABLE+F_FCB,F_CALL,021H,0dh,030h,0,0,3>    
  93.                                                       ;DOS func  0Dh  thru 030h 
  94. ict4  ICT  <F_ACTIVE+F_RET+F_ENABLE,0,021H,031h,031h,0,0,4>   
  95.                                                       ;DOS func  031h TSR
  96. ict5  ICT  <F_ACTIVE+F_RET2+F_ENABLE+F_FCB,F_CALL,021H,032h,04Bh,0,0,5>   
  97.                                                       ;DOS funcs 032h thru 4Bh
  98. ict6  ICT  <F_ACTIVE+F_RET2+F_ENABLE,0,021H,04Ch,04Ch,0,0,6>   
  99.                                                       ;DOS func  04Ch  EXIT
  100. ict7  ICT  <F_ACTIVE+F_RET2+F_ENABLE+F_FCB,F_CALL,021H,04Dh,0ffh,0,0,7>   
  101.                                                       ;DOS funcs 04Dh thru FFh
  102. ict8  ICT  <F_ACTIVE+F_RET+F_ENABLE,F_CALL,025h,0,0ffh,0,0,8>             
  103.                                                       ;RAW disk I/O
  104. ict9  ICT  <F_ACTIVE+F_RET+F_ENABLE,F_CALL,026h,0,0ffh,0,0,9>             
  105.                                                       ;RAW disk I/O
  106. ict10 ICT  <F_ACTIVE+F_RET+F_ENABLE,0,027h,0,0ffh,0,0,10>             
  107.                                                       ;DOS TSR
  108. ict11 ICT  <F_ACTIVE+F_RET2+F_ENABLE,0,02Eh,0,0ffh,0,0,11>             
  109.                                                       ;DOS undocumented .BAT call
  110.  
  111. ict12 ICT  <0,0,0,0,0,0,12>                                        ;unused
  112. ict13 ICT  <0,0,0,0,0,0,13>                                        ;unused
  113. ict14 ICT  <0,0,0,0,0,0,14>                                        ;unused
  114. ict15 ICT  <0,0,0,0,0,0,15>                                        ;unused
  115.  
  116.  
  117. ;*******************************************************
  118. ;    E N D    C O N F I G U R A T I O N
  119. ;*******************************************************
  120.  
  121.         subttl  Resident Storage
  122.         page
  123.  
  124. ;
  125. ; Things defined here are present even after we become resident and
  126. ; exit to DOS.
  127. ;
  128.  
  129.  
  130. ;********************************************************
  131. ;
  132. ; Index table pointing to all ICT's
  133. ;
  134. ;********************************************************
  135.  
  136. ict_index label word
  137.         dw      offset ict0
  138.         dw      offset ict1
  139.         dw      offset ict2
  140.         dw      offset ict3
  141.         dw      offset ict4
  142.         dw      offset ict5
  143.         dw      offset ict6
  144.         dw      offset ict7
  145.         dw      offset ict8
  146.         dw      offset ict9
  147.         dw      offset ict10
  148.         dw      offset ict11
  149.         dw      offset ict12
  150.         dw      offset ict13
  151.         dw      offset ict14
  152.         dw      offset ict15
  153.  
  154. ;********************************************************
  155. ;
  156. ; Index table pointing to all handlers
  157. ;
  158. ;********************************************************
  159.  
  160. hndlr_index label word
  161.         dw      offset handler0
  162.         dw      offset handler1
  163.         dw      offset handler2
  164.         dw      offset handler3
  165.         dw      offset handler4
  166.         dw      offset handler5
  167.         dw      offset handler6
  168.         dw      offset handler7
  169.         dw      offset handler8
  170.         dw      offset handler9
  171.         dw      offset handler10
  172.         dw      offset handler11
  173.         dw      offset handler12
  174.         dw      offset handler13
  175.         dw      offset handler14
  176.         dw      offset handler15
  177.  
  178. ;********************************************************
  179. ;
  180. ; Trace table pointers. Actual trace table slung over
  181. ;                       initialization code in TRACE12.ASM
  182. ;
  183. ;********************************************************
  184.  
  185. trace_begin      dw      offset trace_table      ;address of trace table begin 
  186. trace_curr       dw      offset trace_table      ;address of next entry
  187. trace_end        dw      offset trace_table      ;address of end of trace table
  188. trace_bytes      dw      trace_size              ;size of trace table  in bytes
  189.  
  190. ;********************************************************
  191. ;
  192. ; Table of sizes for each trace record type. Must be in same
  193. ; order as record types themselves.
  194. ;
  195. ;********************************************************
  196.  
  197. rec_sizes       label   word
  198.                 dw      size BEFORE
  199.                 dw      size AFTER
  200.                 dw      size FCB
  201.                 dw      size ASCIIZ
  202.  
  203. ;********************************************************
  204. ;
  205. ; Table of INT 21h functions that include an FCB pointer in DS:DX
  206. ;
  207. ;********************************************************
  208.  
  209. FCB_table       label   byte
  210.                 db      0fh,10h,11h,12h,13h,14h,15h,16h,17h,21h,22h,23h,24h,27h,28h
  211. FCB_end         label   byte
  212.  
  213.  
  214. ;********************************************************
  215. ;
  216. ; Table of INT 21h functions that include an ASCIIZ pointer in DS:DX
  217. ;
  218. ;********************************************************
  219.  
  220. ASCIIZ_table    label   byte
  221.                 db      4bh,3ch,3dh,41h,43h,4eh,56h,5ah,5bh,39h,3ah,3bh
  222. ASCIIZ_end      label   byte
  223.  
  224. ;********************************************************
  225. ;
  226. ; Misc storage
  227. ;
  228. ;********************************************************
  229.  
  230. old_int_5       dd      ?                       ;address of previous Prt-Sc routine
  231. our_cs          dw      0                       ;our CS (not for segment checking)
  232. test_cs         dw      0                       ;our normalized CS (for segment checking)
  233. long_addr       dd      0                       ;for long JMP's and CALLs
  234. our_ICT         dw      0                       ;for quick save of our ICT pointer
  235. our_flags       db      0                       ;for quick save of our ICT flags
  236. prt_base        dw      0                       ;base I/O address of printer
  237. ;prt_flag        db      0                       ;non-zero to send output to printer
  238.                 db      255 dup (0)             ;stack for Periscope Int handler
  239. our_tos         dw      0                       ;top of that stack
  240. stack_inuse     db      0                       ;non-zero when above stack is in use
  241. save_ss         dw      0                       ;for stack-swapping
  242. save_sp         dw      0
  243.  
  244.  
  245.         subttl  Interrupt Trappers and Tracing
  246.         page
  247.  
  248. ;********************************************************
  249. ;
  250. ; Interrupt handler entry points for each ICT
  251. ;
  252. ;********************************************************
  253.  
  254. handler macro   ictloc
  255.         cli                             ;*** NO INTERRUPTS!!! ***
  256.         push    bp                      ;save stack pointer, so that...
  257.         mov     bp,sp                   ;...we can ref things via BP
  258.         push    bx                      ;set BX to point to ICT
  259.         mov     bx,offset cs:ictloc
  260.         jmp     int_common              ;goto common code
  261.         endm
  262.  
  263. interrupt proc  far
  264.  
  265. handler0:
  266.         handler ict0
  267.  
  268. handler1:
  269.         handler ict1
  270.  
  271. handler2:
  272.         handler ict2
  273.  
  274. handler3:
  275.         handler ict3
  276.  
  277. handler4:
  278.         handler ict4
  279.  
  280. handler5:
  281.         handler ict5
  282.  
  283. handler6:
  284.         handler ict6
  285.  
  286. handler7:
  287.         handler ict7
  288.  
  289. handler8:
  290.         handler ict8
  291.  
  292. handler9:
  293.         handler ict9
  294.  
  295. handler10:
  296.         handler ict10
  297.  
  298. handler11:
  299.         handler ict11
  300.  
  301. handler12:
  302.         handler ict12
  303.  
  304. handler13:
  305.         handler ict13
  306.  
  307. handler14:
  308.         handler ict14
  309.  
  310. handler15:
  311.         handler ict15
  312.  
  313. int_common:
  314.  
  315.         push    ax
  316.  
  317. ;********************************************************
  318. ;
  319. ; Common code for all trapped INT's.
  320. ;
  321. ; At this point:
  322. ;
  323. ;   BX holds ICT address.
  324. ;   BP points to stack as follows:
  325. ;
  326. ;                   AX
  327. ;                   BX
  328. ;      (BP) ---->   BP
  329. ;               +2  IP    of caller
  330. ;               +4  CS    of caller
  331. ;               +6  FLAGS of caller
  332. ;
  333. ;********************************************************
  334.  
  335. ; At this point we get the int number in AH. We invent an esoteric INT 21H 
  336. ; value for telling the initialization code we are already here
  337.  
  338.         cmp     cs:[bx].ICT_intnum,21h          ;check interrupt # being traced
  339.         jne     notint21                        ;if not 21h go on.
  340.         mov     ax,-4[bp]                       ;get original AX
  341.         cmp     ax,iamhere                      ;is it me ?
  342.         jne     notmyint                        ;no, go on
  343.         mov     word ptr -2[bp],iamhere         ;set BX to flag
  344. notmyint:
  345.         pop     ax                              ;restore ah
  346.         push    ax                              ;restore stack
  347. notint21:
  348.         test    cs:[bx].ICT_flags,F_ENABLE      ;tracing enabled for this ICT?
  349.         jz      no_trace                        ;no, don't trace it
  350.         cmp     ah,cs:[bx].ICT_AH_lo            ;is AH within bounds?
  351.         jb      no_trace                        ;no, don't trace it
  352.         cmp     ah,cs:[bx].ICT_AH_hi
  353.         ja      no_trace                        ;no, don't trace it
  354.  
  355. ;
  356. ; See if we should check caller's CS:IP
  357. ;
  358.  
  359.         test    cs:[bx].ICT_flags,F_BELOW+F_ROM
  360.         jz      int_common3             ;no segment checks to be made
  361.  
  362.         mov     ax,2[bp]                ;get caller's IP
  363.         shr     ax,1                    ;prepare to normalize segment #
  364.         shr     ax,1
  365.         shr     ax,1
  366.         shr     ax,1
  367.         add     ax,4[bp]                ;add in segment
  368.  
  369. ;
  370. ; ------ AX now equals normalized segment #
  371. ;
  372.  
  373.         test    cs:[bx].ICT_flags,F_BELOW
  374.  
  375.         jz      int_common2             ;don't check for invoker below us
  376.         cmp     ax,cs:test_cs           ;is caller below us?
  377.         jb      no_trace                ;yes, don't trace
  378.  
  379. int_common2:
  380.  
  381.         test    cs:[bx].ICT_flags,F_ROM
  382.  
  383.         jz      int_common3             ;don't check for invoker in ROM
  384.         cmp     ax,0c000h               ;is caller in ROM?
  385.         jae     no_trace                ;yes, don't trace
  386.  
  387. int_common3:
  388.  
  389. ;
  390. ; See if we have room for this trace
  391. ;
  392.  
  393.         mov     ax,cs:trace_curr         ;get address of next entry
  394.         push    ax
  395.         add     ax,size BEFORE          ;add size of this record
  396. ;       cmp     ax,offset cs:last_byte  ;would record fit?
  397.         cmp     ax,cs:trace_end         ;would record fit?
  398.         pop     ax
  399.         jb      yes_trace               ;yes, there's room
  400.  
  401. no_trace:
  402.  
  403. ;
  404. ; We are not to trace this INT, for whatever reason.
  405. ; Just go to original handler, and return to caller (not to us).
  406. ;
  407.  
  408.         mov     ax,word ptr cs:[bx].ICT_orig_hndlr
  409.         mov     word ptr cs:long_addr,ax
  410.         mov     ax,word ptr cs:[bx].ICT_orig_hndlr+2
  411.         mov     word ptr cs:long_addr+2,ax
  412.         pop     ax
  413.         pop     bx
  414.         pop     bp
  415.         jmp     cs:long_addr    ;let original handler return to caller
  416.  
  417.  
  418. yes_trace:
  419.  
  420. ;
  421. ; We are to proceed with trace of this INT. Make trace entry.
  422. ;
  423.  
  424.         push    es
  425.         push    di
  426.  
  427. ;
  428. ; At this point:
  429. ;
  430. ;   AX holds offset to next trace entry.
  431. ;   BX holds ICT address.
  432. ;   BP points to stack as follows:
  433. ;
  434. ;                   DI
  435. ;                   ES
  436. ;                   AX
  437. ;                   BX
  438. ;      (BP) ---->   BP
  439. ;               +2  IP    of caller
  440. ;               +4  CS    of caller
  441. ;               +6  FLAGS of caller
  442. ;
  443.  
  444.         mov     di,ax                   ;set ES:DI to next trace entry
  445.         mov     ax,cs
  446.         mov     es,ax
  447.         cld                             ;forward!!!
  448.         mov     ah,cs:[bx].ICT_intnum   ;get interrupt # being traced
  449.         mov     al,cs:[bx].ICT_num      ;get ICT #, make BEFORE record type
  450.         stosw
  451.         mov     ax,-4[bp]               ;original AX
  452.         stosw
  453.         mov     ax,-2[bp]               ;original BX
  454.         stosw
  455.         mov     ax,cx
  456.         stosw
  457.         mov     ax,dx
  458.         stosw
  459.         mov     ax,-6[bp]               ;original ES
  460.         stosw
  461.         mov     ax,ds
  462.         stosw
  463.         mov     ax,ss
  464.         stosw
  465.         mov     ax,bp                   ;original SP
  466.         add     ax,2
  467.         stosw
  468.         mov     ax,si
  469.         stosw
  470.         mov     ax,-8[bp]               ;original DI
  471.         stosw
  472.         mov     ax,[bp]                 ;original BP
  473.         stosw
  474.         mov     ax,4[bp]                ;caller's CS
  475.         stosw
  476.         mov     ax,2[bp]                ;caller's IP
  477.         stosw
  478.  
  479.         mov     cs:trace_curr,di         ;save spot for next trace entry
  480.         inc     cs:[bx].ICT_hits        ;bump number of traces made for this ICT
  481.  
  482. ;
  483. ; We're done with the BEFORE trace. See if we are to do an FCB or ASCIIZ
  484. ; trace record.
  485. ;
  486.  
  487.         test    cs:[bx].ICT_flags,F_FCB
  488.         jz      no_FCB                  ;no, we are definitely not supposed to
  489.         cmp     cs:[BX].ICT_intnum,021h ;is this an INT 21h?
  490.         jnz     no_FCB                  ;no, can't trace it then
  491.  
  492. ;
  493. ; Search through ASCIIZ function table, to see if function that was called
  494. ; is one that contains an ASCIIZ pointer in DS:DX
  495. ;
  496.  
  497.         mov     ax,-4[bp]               ;get AX at time of call
  498.         push    cx
  499.         mov     di,offset cs:ASCIIZ_table
  500.         mov     cx,offset cs:ASCIIZ_end
  501.         sub     cx,di                   ;CX now has size of table
  502.         mov     al,ah                   ;get function to AL
  503.         repnz   scasb                   ;see if it's in table
  504.         pop     cx
  505.         jz      trace_ASCIIZ            ;it's there, so do ASCIIZ trace
  506.  
  507. ;
  508. ; Search through FCB function table, to see if function that was called
  509. ; is one that contains an FCB pointer in DS:DX
  510. ;
  511.  
  512.         push    cx
  513.         mov     di,offset cs:FCB_table
  514.         mov     cx,offset cs:FCB_end
  515.         sub     cx,di                   ;CX now has size of table
  516.         repnz   scasb                   ;see if it's in table
  517.         pop     cx
  518.         jnz     no_FCB                  ;no FCB or ASCIIZ trace called for
  519.  
  520. ;
  521. ; We are to do trace of FCB pointed to by DS:DX
  522. ;
  523.  
  524.         mov     al,00100000b            ;trace record number for FCB trace
  525.         mov     ah,size FCB             ;size of record
  526.         jmp     short trace_common      ;rest is common code
  527.  
  528. trace_ASCIIZ:
  529.  
  530. ;
  531. ; We are to do trace of ASCIIZ string pointed to by DS:DX
  532. ;
  533.  
  534.         mov     al,00110000b            ;trace record number for ASCIIZ trace
  535.         mov     ah,size ASCIIZ          ;size of record
  536.  
  537. trace_common:
  538.  
  539. ;
  540. ; Copy bytes from DS:DX to new ASCIIZ or FCB trace record.
  541. ;
  542. ; At this point:
  543. ;
  544. ;   AL holds trace record type, properly positioned in bits 7-4
  545. ;   AH holds size of record that we're doing (the full record)
  546. ;
  547.  
  548.         sub     ah,2                    ;minus two bytes for record header
  549.         mov     di,cs:trace_curr         ;see if there's room...
  550.         push    di
  551.         push    ax
  552.         mov     al,ah                   ;get record size to AX
  553.         xor     ah,ah
  554.         add     di,ax
  555.         cmp     di,cs:trace_end
  556.         pop     ax
  557.         pop     di
  558.         jae     no_FCB                  ;no room
  559.         push    ax                      ;save AX over this
  560.         mov     ah,cs:[bx].ICT_intnum   ;start header with interrupt #
  561.         or      al,cs:[bx].ICT_num      ;add ICT number to trace type
  562.         stosw                           ;start new record with it
  563.         pop     ax                      ;restore AX
  564.         push    cx
  565.         push    si
  566.         mov     si,dx                   ;access DS:DX as DS:SI
  567.         mov     cl,ah                   ;record size to CX
  568.         xor     ch,ch
  569.         rep     movsb                   ;that's how many to copy
  570.         pop     si
  571.         pop     cx
  572.         mov     cs:trace_curr,di         ;save offset to next record
  573.  
  574. no_FCB:                                 ;end of FCB/ASCIIZ tracing
  575.  
  576.                                         ;end of tracing, period
  577.  
  578.         test     cs:[bx].ICT_flags2,F_CALL 
  579.         jnz      call_old               ;if marked for call then call far
  580.  
  581.         ;else: for ints that don't return like 20h and 27h then just jmp far
  582.  
  583.         mov     ax,word ptr cs:[bx].ICT_orig_hndlr
  584.         mov     word ptr cs:long_addr,ax
  585.         mov     ax,word ptr cs:[bx].ICT_orig_hndlr+2
  586.         mov     word ptr cs:long_addr+2,ax
  587.  
  588.         pop     di
  589.         pop     es
  590.         pop     ax
  591.         pop     bx
  592.         pop     bp
  593.         jmp     cs:long_addr            ;invoke original handler via jump
  594.  
  595. call_old: 
  596.  
  597. ;
  598. ; Having traced all of those, now invoke original interrupt handler. Have
  599. ; it return to us, not the original caller of the interrupt.
  600. ;
  601.  
  602.         mov     cs:our_ICT,bx           ;save ICT pointer for a nanosecond
  603.         mov     al,cs:[bx].ICT_flags    ;save copy of flags that we can get to
  604.         mov     cs:our_flags,al
  605.  
  606.         mov     ax,word ptr cs:[bx].ICT_orig_hndlr
  607.         mov     word ptr cs:long_addr,ax
  608.         mov     ax,word ptr cs:[bx].ICT_orig_hndlr+2
  609.         mov     word ptr cs:long_addr+2,ax
  610.  
  611.         pop     di
  612.         pop     es
  613.         pop     ax
  614.         pop     bx
  615.         pop     bp
  616.         push    cs:our_ICT              ;save ICT pointer on stack
  617.         test    cs:our_flags,F_RET      ;should we push flags?
  618.         jnz     no_flags                ;no, cause they'd be left on stack
  619.         pushf                           ;yes, give handler some flags to drop
  620.  
  621. no_flags:
  622.         call    cs:long_addr            ;invoke original handler
  623.  
  624.  
  625. ;
  626. ; We're back from the real interrupt handler, and can make the "after" trace.
  627. ; Our ICT address is on stack.
  628. ;
  629.  
  630.         sti                             ;give world a crack at interrupts
  631.         nop
  632.         nop
  633.         cli                             ;*** NO INTERRUPTS!!! ***
  634.         push    bp                      ;establish stack reference
  635.         mov     bp,sp
  636.         pushf                           ;save resultant flags
  637.         push    es
  638.         push    di
  639.         push    ax
  640.         push    bx
  641.  
  642. ;
  643. ; At this point:
  644. ;
  645. ;                     BX
  646. ;                     AX
  647. ;                     DI
  648. ;                     ES
  649. ;                     FLAGS (as returned by real interrupt)
  650. ;     (BP) -------->  BP
  651. ;                     ICT address
  652. ;                     IP of caller
  653. ;                     CS of caller
  654. ;                     FLAGS of original caller
  655. ;
  656.  
  657.         mov     bx,2[bp]                ;recover ICT address
  658.         mov     di,cs:trace_curr         ;room for "after" trace entry?
  659.         push    di
  660.         add     di,size AFTER
  661. ;       cmp     di,offset cs:last_byte
  662.         cmp     di,cs:trace_end
  663.         pop     di
  664.         jae     no_after                ;no, skip it
  665.         mov     ax,cs                   ;make ES:DI point to next entry
  666.         mov     es,ax
  667.         cld                             ;forward!!!
  668.         mov     ah,cs:[bx].ICT_intnum   ;get interrupt #
  669.         mov     al,cs:[bx].ICT_num      ;get ICT #, make AFTER record type
  670.         or      al,00010000b
  671.         stosw
  672.         mov     ax,-8[bp]               ;AX at int's return
  673.         stosw
  674.         mov     ax,-10[bp]              ;BX at int's return
  675.         stosw
  676.         mov     ax,cx
  677.         stosw
  678.         mov     ax,dx
  679.         stosw
  680.         mov     ax,-4[bp]               ;ES at int's return
  681.         stosw
  682.         mov     ax,ds
  683.         stosw
  684.         mov     ax,si
  685.         stosw
  686.         mov     ax,-6[bp]               ;DI at int's return
  687.         stosw
  688.         mov     ax,[bp]                 ;BP at int's return
  689.         stosw
  690.         mov     ax,-2[bp]               ;FLAGS at int's return
  691.         stosw
  692.  
  693.         mov     cs:trace_curr,di         ;save offset to next entry
  694.  
  695. no_after:
  696.  
  697. ;
  698. ; All done making "after" trace, or we've skipped it cause there was
  699. ; no room for it.
  700. ;
  701. ; Now just exit back to the original caller.
  702. ;
  703.  
  704.         mov     al,cs:[bx].ICT_flags    ;save flags where we can get to them
  705.         mov     cs:our_flags,al
  706.         pop     bx
  707.         pop     ax
  708.         pop     di
  709.         pop     es
  710.         popf
  711.         pop     bp
  712.         pop     cs:our_ICT      ;drop ICT address without affecting flags
  713.  
  714. ;
  715. ; HOW we exit is extremely important. We must exit the same way that the
  716. ; real interrupt does.
  717. ;
  718.  
  719.         pushf                           ;save current flags in case we return them
  720.         test    cs:our_flags,F_RET
  721.         jnz     exit_ret
  722.         test    cs:our_flags,F_RET2
  723.         jnz     exit_ret2
  724.  
  725. ;
  726. ; Assume IRET.
  727. ;
  728.  
  729. exit_iret:
  730.         popf                    ;exit via IRET, reloading original flags
  731.         STI                     ;Allow interrupts now
  732.         iret
  733.  
  734. exit_ret2:
  735.         popf                    ;exit via RET 2, discarding original flags
  736.         STI                     ;Allow interrupts now
  737.         ret     2
  738.  
  739. exit_ret:
  740.         popf                    ;exit via far RET, leaving original flags
  741.         STI                     ;Allow interrupts now
  742.         ret
  743.  
  744. interrupt endp
  745.  
  746.         page
  747. ;*********************************************
  748. ;
  749. ; Handle main menu selection whose ASCII keypress is in AL.
  750. ;
  751. ; Returns: CARRY SET if we should loop back to main menu.
  752. ;          CARRY CLEAR to exit.
  753. ;
  754. ;*********************************************
  755.  
  756. do_main proc    near
  757.         push    ax
  758.         cmp     al,'P'          ;select printer?
  759.         jnz     do_main1        ;no
  760.         call    selprint        ;yes, do it
  761.         stc                     ;"Loop back to main menu" flag
  762.         jmp     short do_main9
  763.  
  764. do_main1:
  765.         cmp     al,'S'          ;select screen?
  766.         jnz     do_main2        ;no
  767.         call    selvideo        ;yes, do it
  768.         stc                     ;"Loop back to main menu" flag
  769.         jmp     short do_main9
  770.  
  771. do_main2:
  772.         cmp     al,'T'          ;Dump Traces?
  773.         jnz     do_main3        ;no
  774.         call    do_traces       ;yes, do it
  775.         stc                     ;"Loop back to main menu" flag
  776.         jmp     short do_main9
  777.  
  778. do_main3:
  779.         cmp     al,'E'          ;Enable ICT?
  780.         jnz     do_main4        ;no
  781.         mov     al,F_ENABLE     ;yes, get bit value to set/clear
  782.  
  783. do_main3b:
  784.         call    do_enable       ;enable/disable F_ENABLE per AL
  785.         stc                     ;"Loop back to main menu" flag
  786.         jmp     short do_main9
  787.  
  788. do_main4:
  789.         cmp     al,'D'          ;Disable ICT?
  790.         jnz     do_main5        ;no
  791.         mov     al,0            ;yes, get bit value to set/clear
  792.         jmp     do_main3b
  793.  
  794. do_main5:
  795.         cmp     al,'L'          ;List ICT's?
  796.         jnz     do_main6        ;no
  797.         call    disp_active     ;yes, do it
  798.         stc                     ;"Loop back to main menu" flag
  799.         jmp     short do_main9
  800.  
  801. do_main6:
  802.         cmp     al,'C'          ;Clear trace table?
  803.         jnz     do_main7        ;no
  804.         call    zap_hits        ;yes, do it
  805.         stc                     ;"Loop back to main menu" flag
  806.         jmp     short do_main9
  807.  
  808. do_main7:
  809.         cmp     al,'Q'          ;Quit?
  810.         jnz     do_main7a       ;no
  811.         clc                     ;"Exit" flag
  812.         jmp     short do_main9
  813.  
  814. do_main7a:
  815.         cmp     al,'W'          ;PrtSc call?
  816.         jnz     do_main8        ;no
  817.         call    prt_sc
  818.         clc                     ;"Exit" flag
  819.         jmp     short do_main9
  820.  
  821. do_main8:
  822.         cmp     al,'F'          ;F_FCB toggle?
  823.         jnz     do_main8B       ;no
  824.         call    do_fcb          ;yes, toggle something
  825.         stc                     ;"Loop back to main menu" flag
  826.         jmp     short do_main9
  827.  
  828. do_main8b:
  829.  
  830. ; ------ Unknown selection
  831.  
  832.         stc                     ;"Loop back to main menu" flag
  833.  
  834. do_main9:
  835.         pop     ax
  836.         ret
  837. do_main endp
  838.  
  839.  
  840.         subttl  Interpretation - Misc Routines
  841.         page
  842. ;********************************************************************
  843. ;*                                                                  *
  844. ;*  This file contains the routines that interpret selected         *
  845. ;*  BEFORE trace records and print out sensible summaries of        *
  846. ;*  their meanings. This sure beats having to read a lotta hex      *
  847. ;*  function codes.                                                 *
  848. ;*                                                                  *
  849. ;*  The main routine - interp() - is called just after we've        *
  850. ;*  printed all of the trace record in hex. If this record is       *
  851. ;*  one that we know about, we should now print a one-line          *
  852. ;*  interpretation of the record. This is done via lower-level      *
  853. ;*  routines called by interp() per the INT in the record.          *
  854. ;*                                                                  *
  855. ;********************************************************************
  856.  
  857.  
  858. ;********************************************************************
  859. ;
  860. ; Interpret BEFORE trace record at [SI].
  861. ;
  862. ;********************************************************************
  863.  
  864. interp  proc    near
  865.         push    bx
  866.         push    ax
  867.         mov     ah,[SI].B_int           ;get INT type
  868.         mov     bx,offset interp_tab    ;point to table of handlers
  869.  
  870. interp2:
  871.         cmp     ah,[bx]                 ;does this handler go with this INT?
  872.         jnz     interp5                 ;no
  873.         mov     bx,1[bx]                ;yes, get handler's address
  874.         call    bx                      ;call that handler
  875.         jmp     interp9                 ;exit
  876.  
  877. interp5:
  878.         add     bx,3                    ;up to next entry in table
  879.         cmp     bx,offset interp_end    ;searched whole table yet?
  880.         jb      interp2                 ;no, try next one
  881.  
  882. interp9:
  883.  
  884.         pop     ax
  885.         pop     bx
  886.         ret
  887. interp  endp
  888.  
  889. ;
  890. ; Table of interpreters for various interrupts.
  891. ;
  892. ; Each entry is as follows:
  893. ;
  894. ;       db      <intnum>                ;interrupt number
  895. ;       dw      offset <handler>        ;address of handler to interpret this int's record
  896. ;
  897. ;
  898.  
  899. interp_tab      label   byte
  900.                 db      013h                    ;INT 13h is Diskette I/O
  901.                 dw      offset interp_13        ;handler for INT 13h
  902.                 db      020h                    ;INT 20h is DOS Program exit
  903.                 dw      offset interp_20        ;handler for INT 20h
  904.                 db      021h                    ;INT 21h is DOS Function Handler
  905.                 dw      offset interp_21        ;handler for INT 21h
  906.                 db      025h                    ;INT 025H is DOS ABSOLUTE DISK READ
  907.                 dw      offset interp_25
  908.                 db      026h                    ;INT 026H is DOS ABSOLUTE DISK WRITE
  909.                 dw      offset interp_25        ;uses same interpreter
  910.                 db      027h                    ;INT 027H is DOS TSR
  911.                 dw      offset interp_27        ;uses same interpreter
  912.                 db      02Eh                    ;INT 02EH is undoc DOS .BAT
  913.                 dw      offset interp_2E        ;uses same interpreter
  914. interp_end      label   byte                    ;end of table
  915.  
  916.         subttl  Interpretation - INT 13 (Diskette I/O)
  917.         page
  918. ;
  919. ; Tables used to interpret INT 13h  in TRACE1E.AIC
  920. ;
  921.  
  922. Floppy_or_Hard  db      0,"Floppy:",0
  923.                 db      080h,"Fixed:",080h
  924.  
  925. Cyl_or_Track    db      0,"Track:",0
  926.                 db      080h,"Cyl:",080h
  927.  
  928.  
  929. int13_line      label   byte
  930.                 db      cr,lf,"       "
  931.                 db      Edit_Call
  932. int13_F_or_H    db      0
  933.                 dw      offset Floppy_or_Hard
  934.                 dw      offset table_print
  935.                 db      Edit_Dec8
  936. int13_drive     db      0
  937.                 db      " Head:"
  938.                 db      Edit_Dec8
  939. int13_head      db      0
  940.                 db      " "
  941.                 db      Edit_Call
  942. int13_C_or_T    db      0
  943.                 dw      offset Cyl_or_Track
  944.                 dw      offset table_print
  945.                 db      Edit_Dec16
  946. int13_cyl       dw      0
  947.                 db      " Sect:"
  948.                 db      Edit_Dec8
  949. int13_sect      db      0
  950.                 db      " #Sects:"
  951.                 db      Edit_Dec8
  952. int13_numsects  db      0
  953.                 db      " "
  954.                 db      Edit_Call
  955. int13_func      db      0
  956.                 dw      offset int13_functab
  957.                 dw      offset table_print
  958.                 db      Edit_End
  959.  
  960. ;**************************************************
  961. ;
  962. ; Interpret INT 13h BEFORE trace record at [SI]
  963. ;
  964. ;**************************************************
  965.  
  966. interp_13 proc  near
  967.         push    dx
  968.         push    cx
  969.         push    ax
  970.         mov     dx,[SI].B_dx            ;get DX at time of INT
  971.         mov     al,dl                   ;Get drive #
  972.         and     al,080h                 ;isolate floppy/hard bit
  973.         mov     int13_F_or_H,al         ;use it to select device name...
  974.         mov     int13_C_or_T,al         ;...as well as cylinders/tracks
  975.         and     dl,07fh                 ;isolate drive #
  976.         mov     int13_drive,dl
  977.         mov     int13_head,dh           ;store head #
  978.         mov     cx,[SI].B_cx            ;get CX at time of INT
  979.         xor     ax,ax                   ;calc 10-bit cylinder #
  980.         mov     al,cl
  981.         shl     ax,1
  982.         shl     ax,1
  983.         mov     al,ch
  984.         mov     int13_cyl,ax            ;save as word
  985.         and     cl,00111111b            ;isolate sector #
  986.         mov     int13_sect,cl
  987.         mov     ax,[SI].B_ax            ;get AX at time of INT
  988.         mov     int13_numsects,al
  989.         mov     int13_func,ah
  990.         mov     dx,offset int13_line    ;now print edited line
  991.         call    print_edit
  992.         pop     ax
  993.         pop     cx
  994.         pop     dx
  995.         ret
  996. interp_13 endp
  997.  
  998.         subttl  Interpretation - INT 20h (DOS)
  999.         page
  1000.  
  1001. int20_line label byte
  1002.            db      cr,lf,"       DOS: interrupt 20h - terminate program"
  1003.            db      Edit_End
  1004.  
  1005. ;**************************************************
  1006. ;
  1007. ; Interpret INT 20h BEFORE trace record at [SI]
  1008. ;
  1009. ;**************************************************
  1010.  
  1011. interp_20 proc  near
  1012.         push    dx
  1013.         mov     dx,offset int20_line
  1014.         call    print_edit
  1015.         pop     dx
  1016.         ret
  1017. interp_20 endp
  1018.  
  1019.  
  1020.  
  1021.  
  1022.         subttl  Interpretation - INT 21h (DOS)
  1023.         page
  1024. ;
  1025. ; Tables used in interpreting INT 21h
  1026. ;
  1027.         include b:trace1.aic
  1028.  
  1029.  
  1030.  
  1031. int21_line label byte
  1032.                 db      cr,lf,"       DOS: "
  1033.                 db      Edit_Call
  1034. int21_func      db      0
  1035.                 dw      offset int21_functab
  1036.                 dw      offset table_print
  1037.                 db      Edit_End
  1038.  
  1039. ;**************************************************
  1040. ;
  1041. ; Interpret INT 21h BEFORE trace record at [SI]
  1042. ;
  1043. ;**************************************************
  1044.  
  1045. interp_21 proc  near
  1046.         push    dx
  1047.         push    ax
  1048.         mov     ax,[SI].B_ax            ;get AX at time of int
  1049.         mov     byte ptr int21_func,ah  ;use it to select function
  1050.         mov     dx,offset int21_line
  1051.         call    print_edit
  1052.         pop     ax
  1053.         pop     dx
  1054.         ret
  1055. interp_21 endp
  1056.  
  1057.         subttl  Interpretation - INT 25h and 26h (Absolute disk I/O)
  1058.         page
  1059. ;
  1060. ; Tables used to interpret INT's 25h and 26h
  1061. ;
  1062.  
  1063. int25_functab   label   byte
  1064.                 db      025h,"Read",0
  1065.                 db      026h,"Write",080h
  1066.  
  1067. int25_line      label   byte
  1068.                 db      cr,lf,"       DOS Absolute "
  1069.                 db      Edit_Call
  1070. int25_func      db      0
  1071.                 dw      offset int25_functab
  1072.                 dw      offset table_print
  1073.                 db      " Drive:"
  1074.                 db      Edit_Dec8
  1075. int25_drv       db      0
  1076.                 db      " Sector:"
  1077.                 db      Edit_Dec16
  1078. int25_sect      dw      0
  1079.                 db      " #Sectors:"
  1080.                 db      Edit_Dec16
  1081. int25_numsects  dw      0
  1082.                 db      " Buf "
  1083.                 db      Edit_Word
  1084. int25_seg       dw      0
  1085.                 db      ":"
  1086.                 db      Edit_Word
  1087. int25_off       dw      0
  1088.                 db      Edit_End
  1089.  
  1090. ;**************************************************
  1091. ;
  1092. ; Interpret INT 25h or INT 26h BEFORE trace record at [SI]
  1093. ;
  1094. ;**************************************************
  1095.  
  1096. interp_25 proc  near
  1097.         push    dx
  1098.         push    ax
  1099.         mov     al,[SI].B_int           ;get INT that was done (25h or 26h)
  1100.         mov     int25_func,al           ;move to printline
  1101.         mov     ax,[SI].B_ax            ;get drive # from AL
  1102.         mov     int25_drv,al            ;move to printline
  1103.         mov     ax,[SI].B_dx            ;get starting sector # from DX
  1104.         mov     int25_sect,ax           ;move to printline
  1105.         mov     ax,[SI].B_cx            ;get # sectors from CX
  1106.         mov     int25_numsects,ax       ;move to printline
  1107.         mov     ax,[SI].B_ds            ;get buffer segment from DS
  1108.         mov     int25_seg,ax            ;move to printline
  1109.         mov     ax,[SI].B_bx            ;get buffer offset from BX
  1110.         mov     int25_off,ax            ;move to printline
  1111.         mov     dx,offset int25_line    ;now print edited line
  1112.         call    print_edit
  1113.         pop     ax
  1114.         pop     dx
  1115.         ret
  1116. interp_25 endp
  1117.  
  1118. int27_line label byte
  1119.            db      cr,lf,"       DOS: interrupt 27h - TSR"
  1120.            db      Edit_End
  1121.  
  1122. ;**************************************************
  1123. ;
  1124. ; Interpret INT 27h BEFORE trace record at [SI]
  1125. ;
  1126. ;**************************************************
  1127.  
  1128. interp_27 proc  near
  1129.         push    dx
  1130.         mov     dx,offset int27_line
  1131.         call    print_edit
  1132.         pop     dx
  1133.         ret
  1134. interp_27 endp
  1135.  
  1136. int2E_line label byte
  1137.            db      cr,lf,"       DOS: interrupt 2Eh - Undocumented .BAT service"
  1138.            db      Edit_End
  1139.  
  1140. ;**************************************************
  1141. ;
  1142. ; Interpret INT 2Eh BEFORE trace record at [SI]
  1143. ;
  1144. ;**************************************************
  1145.  
  1146. interp_2E proc  near
  1147.         push    dx
  1148.         mov     dx,offset int2E_line
  1149.         call    print_edit
  1150.         pop     dx
  1151.         ret
  1152. interp_2E endp
  1153.  
  1154.  
  1155.  
  1156.         subttl  Periscope Interrupt Interface
  1157.         page
  1158.  
  1159. ;*****************************************
  1160. ;
  1161. ; This is the interrupt handler use by Periscope to access this code.
  1162. ; It may also be called by SHIFT-PrtSc.
  1163. ;
  1164. ; On entry, AH contains function:
  1165. ;
  1166. ;       1 - 8:   User Breakpoint checks (BU 1 thru BU 8, then GT)
  1167. ;       9 - FFh: User exits (/U 9 thru /U FFh)
  1168. ;       0FFh:    Called by PrtSc
  1169. ;
  1170. ;*****************************************
  1171.  
  1172.         db      "PS"                    ;sentinel that Periscope checks for
  1173. periscope proc  far
  1174.  
  1175. ;
  1176. ; First, make very sure that we aren't being re-entered!!! This would
  1177. ; wipe out our stack which is already in use.
  1178. ;
  1179.  
  1180.         cli
  1181.         test    cs:stack_inuse,0ffh
  1182.         jz      periscope2              ;it's ok
  1183.  
  1184. periscope1:
  1185.  
  1186.         mov     al,0ffh                 ;tell Periscope "No Break, No Command to be executed"
  1187.         iret                            ;busy, call back later
  1188.  
  1189. periscope2:
  1190.  
  1191. ;
  1192. ; If we've been entered via Periscope User Break function (during single-stepping,
  1193. ; with BU 1 thru BU 8 in effect), then exit immediately. Things are slow
  1194. ; enough without us being executed when we have no Breakpoint checking to do.
  1195. ;
  1196.  
  1197.         cmp     ah,9                    ;BU 1 thru BU 8?
  1198.         jb      periscope1              ;yes, exit
  1199.  
  1200.  
  1201. ;
  1202. ; On entry to this periscope int, we ought to save everything but AX,
  1203. ; and switch to our own stack. Periscope itself doesn't require this,
  1204. ; but the PrtSc routine assumes it.
  1205. ;
  1206.  
  1207.         mov     cs:stack_inuse,0ffh     ;mark our stack busy
  1208.         mov     cs:save_ss,ss
  1209.         mov     cs:save_sp,sp
  1210.         mov     ss,cs:our_cs
  1211.         mov     sp,offset our_tos
  1212.         push    cs:save_ss              ;save old stack stuff for later
  1213.         push    cs:save_sp
  1214.         push    bx
  1215.         push    cx
  1216.         push    dx
  1217.         push    si
  1218.         push    di
  1219.         push    es
  1220.         push    ds
  1221.         push    bp
  1222.         mov     ds,cs:our_cs            ;set DS to us for assume ds:code
  1223.         sti
  1224.  
  1225. ;
  1226. ; Give user stats about trace buffer size
  1227. ;
  1228.         mov     ax,trace_bytes
  1229.         mov     word ptr size_trace,ax
  1230. ;       mov     ax,offset last_byte     ;get # free bytes
  1231.         mov     ax,trace_end            ;get # free bytes
  1232.         sub     ax,trace_curr
  1233.         mov     word ptr size_freeb,ax
  1234.         mov     dx,offset size_msg
  1235.         call    print_edit
  1236.  
  1237. periscope_menu:
  1238.  
  1239. ;
  1240. ; Now display menu and get his selection, until we are to exit
  1241. ;
  1242.  
  1243.         mov     dx,offset mainmenu
  1244.         call    print_line              ;put up main menu
  1245.         call    feed                    ;extra CRLF's for printer
  1246.         call    key                     ;get keypress
  1247.         call    do_main                 ;process it
  1248.         jc      periscope_menu          ;we are to loop back
  1249.         mov     dx,offset shadows       ;give him exit message
  1250.         call    print_line
  1251.  
  1252.  
  1253. periscope_exit:
  1254.  
  1255. ;
  1256. ; Restore regs and original stack. AX is already set to return result.
  1257. ;
  1258.  
  1259.         cli
  1260.         pop     bp
  1261.         pop     ds
  1262.         pop     es
  1263.         pop     di
  1264.         pop     si
  1265.         pop     dx
  1266.         pop     cx
  1267.         pop     bx
  1268.         pop     cs:save_sp      ;restore original stack
  1269.         pop     cs:save_ss
  1270.         mov     ss,cs:save_ss
  1271.         mov     sp,cs:save_sp
  1272.         mov     cs:stack_inuse,0        ;mark our stack not busy
  1273.         iret
  1274. periscope endp
  1275.  
  1276. mainmenu        db      cr,lf  
  1277.                 db      "  TRACE Commands:",cr,lf 
  1278.                 db      " Output to:   Trace    Trace     Sel   List    ICT   "
  1279.                 db      " Trace   Cmd   PrtSc",cr,lf
  1280.                 db      "(P)rt (S)crn (E)nable (D)isable (F)CB (T)race (L)ist "
  1281.                 db      "(C)lear (Q)uit (W)rite",cr,lf,"$"
  1282.  
  1283. shadows         db      cr,lf
  1284.                 db      "Back to DOS"
  1285.                 db      cr,lf,"$"
  1286.  
  1287. size_msg        label   byte
  1288.                 db      cr,lf
  1289.                 db      "TraceBuf Bytes:"
  1290.                 db      Edit_Dec16
  1291. size_trace      dw      0
  1292.                 db      " Free Bytes:"
  1293.                 db      Edit_Dec16
  1294. size_freeb      dw      0
  1295.                 db      Edit_End
  1296.  
  1297.         subttl  INT 05 (SHIFT-PrtSc) Handler
  1298.         page
  1299. ;**************************************************
  1300. ;
  1301. ; This is another way (besides Periscope) to talk to the tracer, and
  1302. ; get it to report what it's found. This is not as clean a way as
  1303. ; via Periscope, but it beats nothing if the Periscope board isn't in
  1304. ; the system.
  1305. ;
  1306. ; This routine just calls the Periscope interrupt handler.
  1307. ;
  1308. ;**************************************************
  1309.  
  1310.         if      prt_scr
  1311.  
  1312. PrtSc   proc    far
  1313.         cli
  1314.         push    es
  1315.         push    ax
  1316.         mov     ax,050h                 ;set ES to 0050:0000
  1317.         mov     es,ax                   ;(the print-screen control byte)
  1318.         cmp     byte ptr es:[0],1       ;are we busy with previous request?
  1319.         jz      PrtSc_exit              ;yes, don't do anything
  1320.         mov     byte ptr es:[0],1       ;no, mark us busy now
  1321.         mov     ah,0ffh                 ;call Periscope INT with special arg
  1322.         int     peri_int
  1323.         mov     byte ptr es:[0],0       ;mark us not busy now
  1324.  
  1325. PrtSc_exit:
  1326.         pop     ax
  1327.         pop     es
  1328.         iret
  1329. Prtsc   endp
  1330.  
  1331.         endif
  1332.  
  1333. code    ends
  1334.         end     start
  1335.  
  1336.